import {createPopper} from "@popperjs/core";
import {Instance, OptionsGeneric} from "@popperjs/core/lib/types";

/**
 * 可复用的气泡窗口
 *
 * 用更直接的方式操作 dom，而不使用 vue 进行控制
 *
 * 场景：
 * - 窗口内容不变，但是依附组件会发生变化的情况下使用
 *
 * 原理：
 * - 基于 popover.js，与 el-popover 底层一致
 */
export class Popper {
    /**
     * 窗口实例
     */
    public instance: Instance | undefined;
    /**
     * 气泡窗口 dom 对象
     */
    public popover: HTMLElement | undefined;
    /**
     * 气泡窗口依附的 dom 对象
     */
    public reference: HTMLElement | undefined;
    /**
     * 气泡窗口参数设置
     */
    public option: OptionsGeneric = {};

    /**
     * 简单的调测日志，用于检测组件的状态变化，popper.js 高级应用会用到
     */
    private post_placement: string | undefined;
    private logger: TModifier = {
        phase: 'main',
        enabled: true,
        name: 'logger',
        fn: ({state}: { state: any }) => {
            // 方向的变化
            if (this.post_placement !== state.placement) {
                this.post_placement = state.placement;
                console.log(this.post_placement);
            }

            // 角标的位置信息
            const {arrow} = state.elements;
            if (arrow) {
                console.log(state.modifiersData.arrow);
                if (state.modifiersData.arrow.centerOffset !== 0) {
                    arrow.setAttribute('data-hide', '');
                } else {
                    arrow.removeAttribute('data-hide');
                }
            }
        },
    };

    /**
     * 增加日志检测
     */
    public pushLogger(): void {
        if (!this.options.modifiers) {
            this.options.modifiers = [];
        }
        this.option.modifiers.push(this._logger);
    }

    /**
     * 显示气泡窗口
     */
    public display(): void {
        if (this.popover) {
            // don't worry about the issue of attributes cannot be obtained when displaying.
            this.popover.classList.remove('hidden');
        }
    }

    /**
     * 隐藏气泡窗口
     */
    public hidden(): void {
        if (this.popover) {
            this.popover.classList.add('hidden');
        }
    }

    /**
     * 初始化气泡窗口，重新绑定窗口和引用之间的关系
     */
    public create(): Instance {
        this.display();

        // destroy the popover if it exists.
        if (this.instance) {
            this.instance.destroy();
        }

        // Pass the button, the tooltip, and some options, and Popper will do the
        // magic positioning for you:
        this.instance = createPopper(this.reference!, this.popover!, this.option);
        console.log(this.instance);
        return this.instance;
    }

    /**
     * 窗口点击事件，除了触发组件和弹窗组件，任何点击事件都要关闭窗口
     */
    public windowsEvent = (evt: Event): void => {
        if (this.instance) {
            const target: EventTarget = evt.target;
            if (!this.popover.contains(target as Node) && !this.reference?.contains(target as Node)) {
                this.hidden();
            }
        }
    }
}